home *** CD-ROM | disk | FTP | other *** search
/ Chip 1996 November / CHIP Kasım 1996.iso / prog / tw / tfw.5 / WINHOST.SLT < prev   
Text File  |  1994-12-07  |  39KB  |  1,369 lines

  1. //
  2. //   W I N H O S T . S L T
  3. //
  4. //   Copyright (C) 1988-1994 deltaComm Development.
  5. //
  6. //   - Written by Colin Sampaleanu.
  7. //   - Modifications by Jeff Woods, Feb '91, to add help function and support
  8. //     for locked modems.
  9. //   - Modifications by Dan Horn, Nov '92, fixed 'floating' timer bug.
  10. //   - Thanks to Jon Fleming for his help in porting this to Windows.
  11. //
  12. //   This is a Host Mode for Telix, written as a script file.
  13. //   To configure Host Mode parameters such as passwords, run the 'WCONFIG'
  14. //   script. That script is run automatically if the Host Mode configuration
  15. //   file 'WINHOST.CNF' is missing.
  16. //
  17. //   This script will only work with Hayes compatible modems, but may be
  18. //   modified for operation with other modems.
  19. //
  20. //////////////////////////////////////////////////////////////////////////////
  21.  
  22.  
  23. // Parameters which are configured from the WinHost configuration file
  24.  
  25. str host_downloads[64],         // Default where users may download from
  26.     host_uploads[64];           // Default where uploaded files go
  27.  
  28. int direct_connect = 0,         // 0 = using a modem
  29.     modem_lock = 0,
  30.     closed_sys = 0;             // 0 = users may sign up on line if not
  31.                                 //  found in the config file
  32.  
  33. // Various global variables
  34.  
  35. str current_caller[31],         // storage of current caller's name
  36.     our_dir[64];                // Winhost directory (either Telix's
  37.                                 //  scripts directory or the contents
  38.                                 //  of the HOST2DIR environment variable
  39.                                 //  if it exists)
  40.  
  41.  
  42. int finished_caller,            // set to TRUE when must return to top
  43.     local_mode,                 // set to TRUE when local test mode
  44.     access_level,               // access level of current caller
  45.     carrier_counts = 1,         // TRUE if should watch Carrier signal
  46.     already_connected = 0,
  47.     exit_requested = 0,         // set to TRUE if Sysop has pressed Esc
  48.     connection_lost = 0,        // set to TRUE when carrier lost
  49.     kill_user = 0,              // set to TRUE when user must be purged
  50.     min_user_name = 5,          // Minimum length of user's name
  51.     user_has_own_dir;           // Flag to restrict the user to one dir
  52.  
  53. int old_scr_chk_key,            // storage for some system variables
  54.     old_cisb_auto,              // which we have to modify and put
  55.     old_zmod_auto,              // back to what they were when done
  56.     old_sound;
  57.  
  58. str old_down_dir[64],
  59.     old_up_dir[64],
  60.     tfw_down_dir[64],
  61.     tfw_up_dir[64],
  62.     old_usage_fname[64];
  63.  
  64. #INCLUDE "WHUTILS.SLT"          // Functions which are shared with the
  65.                                 //  configuration managements script
  66.  
  67. //////////////////////////////////////////////////////////////////////////////
  68. //////////////////////////////////////////////////////////////////////////////
  69.  
  70. main() {
  71.  
  72.   int c;
  73.   str s[80];
  74.  
  75.   tfw_up_dir = _up_dir;
  76.   tfw_down_dir = _down_dir;
  77.   clear_scr;
  78.  
  79.   get_our_dir;
  80.  
  81.   if (read_host_config_file == -1) {
  82.      prints("Unable to read WINHOST.CNF...");
  83.      prints("Running WCONFIG, the Host Mode configuration script.^M^J");
  84.      s = our_dir;
  85.      strcat (s, "WCONFIG");
  86.      calld (s);
  87.      if (read_host_config_file() == -1) {
  88.         prints("Still unable to read WINHOST.CNF. Aborting Host Mode.^M^J");
  89.         return -1;
  90.      }
  91.   }
  92.  
  93.   prints ("Checking existence of download directory ...");
  94.   if (!check_directory (host_downloads)) {
  95.     prints("Aborting Host Mode.");
  96.     return -1;
  97.   }
  98.  
  99.   prints ("Checking existence of upload directory ...");
  100.   if (!check_directory (host_uploads)) {
  101.     prints("Aborting Host Mode.");
  102.     return -1;
  103.   }
  104.  
  105.   old_scr_chk_key = _scr_chk_key;
  106.   _scr_chk_key = 0;
  107.   old_cisb_auto = _cisb_auto;
  108.   _cisb_auto = 0;
  109.   old_zmod_auto = _zmod_auto;
  110.   _zmod_auto = 0;
  111.   old_sound = _sound_on;
  112.   _sound_on = 0;
  113.   old_down_dir = _down_dir;
  114.   old_usage_fname = _usage_fname;
  115.  
  116.   s = our_dir;
  117.   strcat (s, "HOST2.LOG");
  118.   usagelog (s);
  119.  
  120.   if (direct_connect)
  121.     carrier_counts = 0;
  122.   else
  123.     carrier_counts = 1;
  124.  
  125.   if (!direct_connect && carrier())
  126.     already_connected = 1;
  127.  
  128.  
  129.   while (1) {
  130.     _down_dir = host_uploads;   // these are reversed because we are the Host
  131.     old_up_dir = _up_dir;
  132.     _up_dir = host_downloads;   // these are reversed because we are the Host
  133.     user_has_own_dir = 0;
  134.     if (!direct_connect && !already_connected) {
  135.       if (!modem_lock)
  136.         set_cparams(modem_lock, 0, 8, 1);
  137.       delay_scr(3);
  138.       prints("Sending Modem Init string...");
  139.       cputs_tr(_mdm_init_str);
  140.       delay_scr(10);
  141.       prints("Sending Auto-Answer string...");
  142.       cputs_tr(_auto_ans_str);
  143.   }
  144.  
  145.   finished_caller = kill_user = 0;
  146.  
  147.   if (direct_connect)
  148.     carrier_counts = 0;
  149.   else
  150.     carrier_counts = 1;
  151.  
  152.   if (!direct_connect) {
  153.     prints("^M^JHost Mode: Waiting for call...");
  154.     prints("(Press Esc to exit, or 'L' for local test mode).^M^J");
  155.  
  156.     do {
  157.       if (carrier()) {
  158.         local_mode = 0;
  159.         break;
  160.       }
  161.  
  162.       c = inkey();
  163.       if (c) {
  164.         if (c == 27) {
  165.           exit_requested = 1;
  166.           break;
  167.         }
  168.         else if (c == 'l' || c == 'L') {             // local test mode
  169.           prints("Local test mode entered");
  170.           local_mode = 1;
  171.           carrier_counts = 0;
  172.         }
  173.       }
  174.     }
  175.     while (toupper(c) != 'L');
  176.   }
  177.  
  178.   if (!exit_requested) {
  179.     prints("Incoming call. Sysop: press Esc to exit, or END to terminate user.");
  180.  
  181.     do_one_caller();
  182.     if ((connection_lost || kill_user) && carrier_counts && carrier())
  183.       hangup();             // make sure nobody sneaks in
  184.     }
  185.     already_connected = 0;
  186.     if (exit_requested) {
  187.       if (!carrier() && !direct_connect) {
  188.         prints("Sending Modem Init string...");
  189.         cputs_tr(_mdm_init_str);
  190.       }
  191.       _scr_chk_key = old_scr_chk_key;
  192.       _cisb_auto = old_cisb_auto;
  193.       _zmod_auto = old_zmod_auto;
  194.       _sound_on = old_sound;
  195.       _down_dir = tfw_down_dir;
  196.       _up_dir = tfw_up_dir;
  197.       prints("^M^JHost mode script finished.");
  198.       usagelog("*CLOSE*");
  199.       _usage_fname = old_usage_fname;
  200.       return 1;
  201.     }
  202.   }
  203. }
  204.  
  205. //////////////////////////////////////////////////////////////////////////////
  206.  
  207. host_help (str mode, str option) {
  208.  
  209.   str fname[64];
  210.  
  211.   fname = our_dir;
  212.   strcat (fname, mode);
  213.   strcat (fname, "_HELP_");
  214.   StrCat (fname, option);
  215.   StrCat (fname, ".TXT");
  216.  
  217.   if (FileFind (fname, 0)) {
  218.     type_file (fname);
  219.     return (1);
  220.   }
  221.   else {
  222.     printsc ("^MCan't find help file ");
  223.     prints (fname);
  224.     return (0);
  225.   }
  226. }
  227.  
  228. //////////////////////////////////////////////////////////////////////////////
  229.  
  230. do_one_caller() {
  231.  
  232.   str strn[80], fname[64],  s[80], temporary[1];
  233.   int option, status, c, i, i2, f, len;
  234.  
  235.   access_level = 1;
  236.  
  237.   flushbuf();
  238.  
  239.   if (already_connected)
  240.     prints("Already connected, or modem Carrier Detect switch improperly set!");
  241.   else if (carrier_counts) {
  242.     flushbuf();
  243.     if (!modem_lock)
  244.       if (!determine_baud())
  245.         ;                     // do something else here if this is a problem
  246.   }
  247.  
  248.   delay_scr(20);
  249.   if (type_file("LOGO.MSG") == -1) {
  250.     s = our_dir;
  251.     strcat (s, "LOGO.MSG");
  252.     type_file (s);
  253.   }
  254.  
  255.   flushbuf();
  256.  
  257.   get_user_name ();
  258.  
  259.   access_level = setup_user(3);
  260.  
  261.   if (access_level) {
  262.     ustamp("Logon by ", 1, 0);
  263.     ustamp(current_caller, 0, 1);
  264.   }
  265.   else {
  266.     ustamp("Failed logon attempt by ", 1, 0);
  267.     ustamp(current_caller, 0, 1);
  268.     send_goodbye ();
  269.     if (carrier_counts) {
  270.       delay_scr(10);
  271.       hangup();
  272.     }
  273.     return;
  274.   }
  275.  
  276.   if (type_file("WELCOME.MSG") == -1) {
  277.     s = our_dir;
  278.     strcat (s, "WELCOME.MSG");
  279.     type_file (s);
  280.   }
  281.  
  282.   while (1) {
  283.     if (finished_caller)
  284.     return;
  285.  
  286.     if (access_level == 3) {
  287.       if (type_file ("MMENU3.TXT") == -1) {
  288.         s = our_dir;
  289.         strcat (s, "MMENU3.TXT");
  290.         if (type_file (s) == -1) {
  291.           host_send("^M^JFiles  Type  Upload  Download  Shell  Chat  Help  Goodbye ? ");
  292.         }
  293.       }
  294.     }
  295.     else {
  296.       if (type_file ("MMENU.TXT") == -1) {
  297.         s = our_dir;
  298.         strcat (s, "MMENU.TXT");
  299.         if (type_file (s) == -1) {
  300.           host_send("^M^JFiles  Type  Upload  Download  Chat  Help  Goodbye ? ");
  301.         }
  302.       }
  303.     }
  304.  
  305.     host_send ("^M^JCommand: ");
  306.     host_input_strn(strn, 1, 1);
  307.     option = toupper(subchr(strn, 0));
  308.     host_send("^M^J");
  309.  
  310.     if (option == 'H') {               // Help
  311.       host_send("^M^JWhich item above do you wish help on? ");
  312.       host_input_strn(strn, 1, 1);
  313.       substr (strn, 0, 1, strn);
  314.       strupper (strn);
  315.       Host_send("^M^J");
  316.       host_help( "H", strn);
  317.     }
  318.  
  319.     if (option == 'F') {               // Files directory
  320.       if (access_level >= 2) {
  321.         host_send("Enter 'filespec' or press Return for *.*,^M^J: ");
  322.         host_input_strn(fname, 64, 1);
  323.         host_send("^M^J");
  324.         ustamp ("Requested file listing of ", 1, 0);
  325.         ustamp (fname, 0, 1);
  326.  
  327.         if (strcmpi (fname, "") == 0) {
  328.           fname = "*.*";
  329.         }
  330.  
  331.         if (just_filename(fname)) {
  332.           strn = _down_dir;
  333.           strcat(strn, fname);
  334.         }
  335.         else if (user_has_own_dir == 1) {
  336.           host_send ("^M^JAccess outside ");
  337.           host_send (_down_dir);
  338.           host_send (" not allowed^M^J");
  339.           strn = _down_dir;
  340.           strcat(strn, "*.*");
  341.         }
  342.         else {
  343.           len = strlen (fname);
  344.           substr (fname, len - 1, 1, temporary);
  345.           if (strcmpi (temporary, "\") == 0) {
  346.             strn = fname;
  347.             strcat (strn, "*.*");
  348.           }
  349.           else {
  350.             strn = fname;
  351.           }
  352.         }
  353.       }
  354.       else {
  355.         strn = _down_dir;
  356.         strcat(strn, "*.*");
  357.         ustamp ("Requested listing of files", 1, 1);
  358.       }
  359.  
  360.       host_show_directory(strn);
  361.       ustamp ("Displayed ", 1, 0);
  362.       ustamp (strn, 0, 1);
  363.     }
  364.  
  365.     else if (option == 'T') {          // Type a file
  366.       host_send("Type what file? ");
  367.       host_input_strn(strn, 64, 1);
  368.       host_send("^M^J");
  369.       ustamp ("Requested to type ", 1, 0);
  370.       ustamp (strn, 0, 1);
  371.  
  372.       if ((access_level == 1) || (user_has_own_dir == 1))
  373.         fnstrip(strn, 3, fname);
  374.       else
  375.         fname = strn;
  376.  
  377.       if (just_filename(fname)) {
  378.         strn = _down_dir;
  379.         strcat(strn, fname);
  380.         fname = strn;
  381.       }
  382.  
  383.       if (!filefind(fname, 0, strn)) {
  384.         host_send("Unable to find ");
  385.         host_send(fname);
  386.         continue;
  387.       }
  388.  
  389.       type_file(fname);
  390.       ustamp ("Typed ", 1, 0);
  391.       ustamp (fname, 0, 1);
  392.     }
  393.  
  394.     else if (option == 'G') {          // Goodbye (Hang-up)
  395.       send_goodbye ();
  396.       ustamp("User logged off.", 1, 1);
  397.       if (carrier_counts) {
  398.         delay_scr(10);
  399.         hangup();
  400.       }
  401.       return;
  402.     }
  403.  
  404.     else if (option == 'C') {          // Chat mode
  405.       prints("Sysop: Press Space to chat, any other key not to.^M^J");
  406.       c = 0;
  407.       _sound_on = 1;
  408.       for (i = 8; i && !c; --i) {
  409.         host_send (".");
  410.         if (carrier_counts && !carrier()) {
  411.           prints("^M^JConnection has been lost, call terminated.^M^J");
  412.           connection_lost = 1;
  413.           finished_caller = 1;
  414.           break;
  415.         }
  416.         cputc('^G');
  417.         tone(523, 20);
  418.         tone(659, 20);
  419.         tone(523, 20);
  420.         tone(659, 20);
  421.         tone(523, 20);
  422.         tone(659, 20);
  423.         for (i2 = 30; i2 && (c = inkey()) == 0; --i2)
  424.         delay_scr(1);
  425.       }
  426.       _sound_on = 0;
  427.       host_send ("^M^J");
  428.       if (finished_caller)
  429.         continue;
  430.       if (c != ' ' || !c) {
  431.         host_send("Sorry, the Sysop is unavailable^M^J");
  432.         continue;
  433.       }
  434.       host_send("The sysop is here!^M^J");
  435.       chatmode(1);
  436.     }
  437.  
  438.     else if (option == 'U') {          // User upload
  439.       option = host_get_prot();
  440.       if (!option)
  441.         continue;
  442.  
  443.       ustamp ("Upload ", 1, 0);
  444.       status = 1;
  445.       if (option == 'T' || option == 'M' || option == 'S' ||
  446.           option == 'Y' || option == 'Z' || option == 'E') {
  447.         ustamp ("with name-transferrring protocol ", 0, 1);
  448.         send_transfer_msg();
  449.         status = receive(option, "");
  450.       }
  451.       else {
  452.         host_send("Upload what file? ");
  453.         host_input_strn(strn, 48, 1);
  454.         host_send("^M^J");
  455.           if (!strn)
  456.             continue;
  457.           ustamp (strn, 0, 1);
  458.           if ((access_level == 1) || (user_has_own_dir == 1)) // if access 1, name and ext only
  459.             fnstrip(strn, 3, fname);
  460.           else
  461.             fname = strn;
  462.  
  463.           if (just_filename(fname)) {
  464.             strn = _up_dir;
  465.             strcat(strn, fname);
  466.             fname = strn;
  467.           }
  468.  
  469.           if (filefind(fname, 23, strn)) {
  470.             host_send("File already exists!^M^J");
  471.             ustamp ("File already exists", 1, 1);
  472.           }
  473.           else {
  474.             send_transfer_msg();
  475.             status = receive(option, fname);
  476.           }
  477.         }
  478.  
  479.         if (status == -2) {                      // Carrier lost
  480.           connection_lost = finished_caller = 1;
  481.           ustamp ("Lost carrier", 1, 1);
  482.         }
  483.         else if (status == -1) {
  484.           host_send("^M^J^M^J^GOne or more files not received!^M^J");
  485.           ustamp ("One or more files not received", 1, 1);
  486.         }
  487.         else {
  488.           ustamp ("Transfer complete", 1, 1);
  489.         }
  490.       }
  491.  
  492.       else if (option == 'D') {          // User download
  493.         option = host_get_prot();
  494.         if (!option)
  495.           continue;
  496.         host_send("Download what file(s)? ");
  497.         host_input_strn(strn, 48, 1);
  498.         host_send("^M^J");
  499.         if (!strn)
  500.           continue;
  501.         ustamp ("Attempt to download ", 1, 0);
  502.         ustamp (strn, 0, 1);
  503.         if ((access_level == 1) || (user_has_own_dir == 1)) // if not level 2, keep only name & ext
  504.           fnstrip(strn, 3, fname);
  505.         else
  506.           fname = strn;
  507.  
  508.         if (just_filename(fname)) {
  509.           strn = _down_dir;
  510.           strcat(strn, fname);
  511.           fname = strn;
  512.         }
  513.  
  514.         if (!filefind(fname, 0, strn)) {
  515.           host_send("Unable to find any matching file(s)!^M^J");
  516.           ustamp ("No such file", 1, 1);
  517.           continue;
  518.         }
  519.  
  520.         status = 1;
  521.         send_transfer_msg();
  522.         status = send(option, fname);
  523.         if (status == -2) {                      // Carrier lost
  524.           connection_lost = finished_caller = 1;
  525.           ustamp ("Lost carrier", 1, 1);
  526.         }
  527.         else if (status == -1) {
  528.           host_send("^M^J^M^J^GOne or more files not sent!^M^J");
  529.           ustamp ("One or more files not sent", 1, 1);
  530.         }
  531.         else {
  532.           ustamp ("Transfer complete", 1, 1);
  533.         }
  534.       }
  535.  
  536.       else if (option == 'S') {          // Remote shell
  537.         ustamp ("Attempted shell", 1, 1);
  538.         if (access_level == 3) {
  539.           host_send("Type EXIT and then press Enter to come back.^M^J");
  540.           if (get_baud() == 300)
  541.             delay_scr(10);
  542.           if (local_mode)
  543.             dos("", 0);
  544.                // See if user has prepared a custom file for shell operation
  545.                // and call that if it exists
  546.           else if (filefind("RSHELL.BAT", 0, strn))
  547.             dos("RSHELL.BAT", 0);
  548.           else {  // otherwise make our own temporary batch file for redirection
  549.  
  550.                   // now want to make a temporary batch file which will be
  551.                   // called to redirect DOS input and output, then shell to
  552.                   // another copy of the command interpreter
  553.             f = fopen("HOSTTEMP.BAT", "w");
  554.             if (f) {
  555.               if (get_port() != 1 && get_port() != 2) {
  556.                 host_send("Remote Shell not supported on this comm port due to DOS limits!^M^J");
  557.                 continue;
  558.               }
  559.  
  560.             strn = "COMx";
  561.             setchr(strn, 3, get_port() + '0'); // get right name to redirect
  562.  
  563.             fputs("CTTY ", f);           // write to batch file
  564.             fputs(strn, f);
  565.             fputs("^M^J", f);
  566.             if (getenv ("COMSPEC", s) == 0) {
  567.               s = "COMMAND.COM";
  568.             }
  569.             fputs (s, f);
  570.             fputs("^M^J", f);
  571.             fputs("CTTY CON^M^J", f);
  572.             fputs("EXIT^M^J", f);
  573.  
  574.             fclose(f);                   // close the file
  575.  
  576.             if (!local_mode)             // call batch file
  577.               dos("HOSTTEMP.BAT", 0);
  578.           }
  579.           else
  580.             host_send("Can't open temporary batch file!^M^J");
  581.         }
  582.       }
  583.       else {
  584.         ustamp ("Request denied", 1, 1);
  585.       }
  586.     }
  587.  
  588.     else if (option == '^Z') {          // Shut down Host Mode
  589.       if (access_level == 3) {
  590.         host_send("Shutting down Host mode. ");
  591.         ustamp("User shut down Host Mode.", 1, 1);
  592.       }
  593.       send_goodbye ();
  594.       ustamp("User logged off.", 1, 1);
  595.       if (carrier_counts)
  596.         hangup();
  597.       finished_caller = 1;
  598.       exit_requested = 1;
  599.     }
  600.   }
  601. }
  602.  
  603. //////////////////////////////////////////////////////////////////////////////
  604.  
  605. host_get_prot() {
  606.  
  607.   str prot[1], strn[1], s[64];
  608.  
  609.   int Option;
  610.  
  611.   prot = "H";
  612.  
  613.   while (strcmpi (prot, "H") == 0) {
  614.  
  615.     if (type_file ("PMENU.TXT") == -1) {
  616.      s = our_dir;
  617.       strcat (s, "PMENU.TXT");
  618.       if (type_file (s) == -1) {
  619.         host_send("^M^JXmodem  1k-Xmodem  G-1k-Xmodem  Ymodem  YmodEm-g  Zmodem^M^J");
  620.         host_send("Help Cancel^M^J");
  621.       }
  622.     }
  623.  
  624.     host_send("Which protocol, or H for help ? ");
  625.     host_input_strn(prot, 1, 1);
  626.     strupper (prot);
  627.     host_send("^M^J");
  628.  
  629.     if (strcmpi (prot, "H") == 0) {
  630.       host_send ("^M^JHelp on which protocol, or ^"A^" for ALL? ");
  631.       host_input_strn (strn, 1, 1);
  632.       substr (strn, 0, 1, strn);
  633.       strupper (strn);
  634.       Host_send("^M^J");
  635.       host_help( "P", strn);
  636.     }
  637.  
  638.     if (strposi("X1GYEZH", prot, 0) == -1)    // if illegal prot or cancel
  639.       prot = "";                              // return 0
  640.   }
  641.  
  642.   return (toupper(subchr(prot, 0)));
  643.  
  644. }
  645.  
  646. //////////////////////////////////////////////////////////////////////////////
  647.  
  648. send_transfer_msg() {
  649.  
  650.   host_send("Ready to transfer file(s)... Press Ctrl-X at least twice to abort^M^J");
  651. }
  652.  
  653. //////////////////////////////////////////////////////////////////////////////
  654. // Determine the baud rate once a Carrier Detect Signal has been detected
  655. // Since no characters were read, the 'CONNECT' string should still be
  656. // in the receive buffer.
  657.  
  658. determine_baud() {
  659.  
  660.   int t3, t12, t24, t48, t96, t144, t192;
  661.   int tmark, stat;
  662.   int new_baud = 0;
  663.  
  664.   printsc("Determining baud... ");
  665.  
  666.   track_free(0);                // clear all existing tracks
  667.  
  668.   t3 = track("CONNECT^M", 0);       // check for connect strings
  669.   t12 = track("CONNECT 1200", 0);
  670.   t24 = track("CONNECT 2400", 0);
  671.   t48 = track("CONNECT 4800", 0);
  672.   t96 = track("CONNECT 9600", 0);
  673.   t144 = track("CONNECT 14400", 0);
  674.   t192 = track("CONNECT 19200", 0);
  675.  
  676.   tmark = timer_start(30);      // wait up to 3 seconds for string
  677.  
  678.   while (!time_up(tmark)) {
  679.     if (!carrier()) {
  680.       track_free(0);            // clear all existing tracks
  681.       timer_free(tmark);        // free existing timer
  682.       return 0;
  683.     }
  684.  
  685.     if (cinp_cnt())
  686.       track_addchr(cgetc());
  687.  
  688.     stat = track_hit(0);
  689.       if (stat == 0)
  690.         continue;
  691.  
  692.     if (stat == t3)
  693.       new_baud = 300;
  694.     else if (stat == t24)
  695.       new_baud = 2400;
  696.     else if (stat == t48)
  697.       new_baud = 4800;
  698.     else if (stat == t96)
  699.       new_baud = 9600;
  700.     else if (stat == t144)
  701.       new_baud = 14400;
  702.     else if (stat == t192)
  703.       new_baud = 19200;
  704.     else
  705.       new_baud = 1200;
  706.  
  707.     break;                      // have baud rate, get out
  708.   }
  709.  
  710.   track_free(0);                // clear all existing tracks
  711.   timer_free(tmark);            // free existing timer
  712.  
  713.   if (!new_baud) {              // time-up without CONNECT string
  714.     prints("Failed!");
  715.     return 0;
  716.   }
  717.  
  718.   printn(new_baud);
  719.   prints("");
  720.   set_cparams(new_baud, get_parity(), get_datab(), get_stopb());
  721.  
  722.   return 1;                     // indicate success
  723.  
  724. }
  725.  
  726. //////////////////////////////////////////////////////////////////////////////
  727.  
  728. type_file(str fname) {
  729.  
  730.   int f;
  731.   str s[80], buf[100];
  732.   int ichar, lines_sent = 0;
  733.  
  734.   f = fopen(fname, "r");
  735.   if (!f)
  736.     return -1;
  737.  
  738.   host_send("^M^J");
  739.  
  740.   while (1) {
  741.     if (carrier_counts)
  742.     if (!carrier()) {
  743.       connection_lost = 1;
  744.       finished_caller = 1;
  745.       fclose(f);
  746.       return 0;
  747.     }
  748.  
  749.     if (fgets(buf, 80, f) == -1) {
  750.       fclose(f);
  751.       return 1;
  752.     }
  753.  
  754.     host_send(buf);
  755.     host_send("^M^J");
  756.     ++lines_sent;
  757.  
  758.     if (lines_sent >= 22) {
  759.       lines_sent = 0;
  760.       host_send("[More]");
  761.       host_input(1);
  762.  
  763.       if (finished_caller) {       // if user inactivity
  764.         fclose(f);
  765.         return 0;
  766.       }
  767.  
  768.       host_send("^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H");
  769.     }
  770.  
  771.     while (cinp_cnt()) {
  772.       ichar = cgetc();
  773.       if (ichar == '^C' || ichar == '^K') {
  774.         host_send("^M^J");
  775.         fclose(f);
  776.         return 1;
  777.       }
  778.     }
  779.   }
  780. }
  781.  
  782. //////////////////////////////////////////////////////////////////////////////
  783.  
  784. host_send(str outstr) {
  785.  
  786.   printsc(outstr);
  787.   if (!local_mode)
  788.     cputs(outstr);
  789.  
  790. }
  791.  
  792. //////////////////////////////////////////////////////////////////////////////
  793.  
  794. host_send_c(int chr) {
  795.  
  796.   printc(chr);
  797.   if (!local_mode)
  798.     cputc(chr);
  799.  
  800. }
  801.  
  802. //////////////////////////////////////////////////////////////////////////////
  803.  
  804. host_input_strn(str buf, int maximum, int echoable) {
  805.  
  806.   int i = 0, key;
  807.  
  808.   while (1) {
  809.     key = host_input(echoable);
  810.     if (!key) {               // timeout or user disconnect
  811.       setchr(buf, 0, 0);      // set string to empty
  812.       return 0;               // indicate there is a problem
  813.     }
  814.  
  815.     if (key == '^M')
  816.       break;
  817.     if (key == 127 || key == 8) {
  818.       if (i) {
  819.         --i;
  820.         host_send_c(key);
  821.       }
  822.       continue;
  823.     }
  824.     if (i < maximum) {
  825.       setchr(buf, i, key);
  826.       i = i + 1;
  827.     }
  828.     else
  829.       i = i + 1;
  830.   }
  831.  
  832.   if (i > maximum)
  833.     i = maximum;
  834.  
  835.   setchr(buf, i, '^0');
  836.  
  837.   if (subchr(buf, 0))
  838.     return 1;
  839.   else
  840.     return 0;
  841.  
  842. }
  843.  
  844. //////////////////////////////////////////////////////////////////////////////
  845.  
  846. host_input(int echoable) {
  847.  
  848.   int c, t;
  849.  
  850.   t = timer_start(2400);         // 4 minutes inactivity allowed
  851.  
  852.   while (1) {
  853.     if (time_up(t) && !direct_connect) {
  854.       host_send("^M^J^M^JInactivity period too long. Connection terminated!^M^J");
  855.       if (carrier_counts)
  856.         hangup();
  857.       finished_caller = 1;
  858.       kill_user = 1;
  859.       break;
  860.     }
  861.  
  862.     if (carrier_counts)
  863.       if (!carrier()) {
  864.         prints("^M^JConnection has been lost, call terminated.^M^J");
  865.         connection_lost = 1;
  866.         finished_caller = 1;
  867.         break;
  868.       }
  869.     if ((c = inkey()) != 0) {
  870.       if (c == 27) {             // ESC key, sysop wants to exit
  871.         finished_caller = 1;
  872.           exit_requested = 1;
  873.           break;
  874.       }
  875.       else if (c == 0x4f00) {    // END key, terminate user
  876.         prints("^M^JUser terminated!");
  877.         ustamp("User terminated!", 1, 1);
  878.         if (carrier_counts)
  879.           hangup();
  880.  
  881.         finished_caller = 1;
  882.         kill_user = 1;
  883.         break;
  884.       }
  885.  
  886.       else if (c <= 255) {
  887.         if (c != 8 && c != 127)
  888.           if (!echoable)
  889.             host_send_c('*');
  890.           else
  891.             host_send_c(c);
  892.         break;
  893.       }
  894.     }
  895.  
  896.     if (!local_mode)
  897.       if (cinp_cnt())  {
  898.         c = cgetc();
  899.         if (c != 8 && c != 127)
  900.           if (!echoable)
  901.             host_send_c('*');
  902.           else
  903.             host_send_c(c);
  904.         break;
  905.       }
  906.   }
  907.  
  908.   timer_free(t);                 // free existing timer
  909.   if (finished_caller)
  910.   return 0;                    // return 0 - no character
  911.  
  912.   return c;                      // return received/pressed character
  913. }
  914.  
  915. //////////////////////////////////////////////////////////////////////////////
  916.  
  917.  
  918. //  This routine maintains an ASCII file in the Telix files directory called
  919. //    WHPASS.TXT.  The format for each line is:
  920.  
  921. //    name;password;working_dir;access_level  (optional comment)
  922.  
  923. //    The name, password, working_dir, and access_level fields MUST be
  924. //    separated by semicolons
  925.  
  926. //    The working_dir field is optional (but the semicolons before and after
  927. //    it are _NOT_).  If there's no working_dir field, the default host
  928. //    upload and download direcories are used.
  929.  
  930. //  The routine searches the file for a line on which the "name" field
  931. //    matches the global variable "current_caller"  (not case sensitive).
  932.  
  933. //  If a match is found, and the user can type a password that matches
  934. //    the "password" field (not case sensitive), the routine returns
  935. //    the integer "access_level".
  936.  
  937. //  If no match is found, the user is given an opportunity to register
  938. //    (at access level 1).
  939.  
  940. //  If the user registers, the file is updated with the new user name,
  941. //    password, and access level (1), and the routine returns 1.
  942.  
  943. //  If the user does not register, or if the user cannot match the password
  944. //    in the file in "maxtries",  or if the user registers and cannot match
  945. //    the password he/she chose in "maxtries", the routine returns 0.
  946.  
  947. setup_user (int maxtries) {
  948.   str password_file[64], line_from_file[80], password_from_file[16],
  949.       name_from_file[31], temporary[16], typed_password[16],
  950.       working_dir[64], last_char[1];
  951.  
  952.   int password_file_handle, field_length, field_start,
  953.       found_password = 0, access_from_file, counter = 0,
  954.       file_ends_in_control_z = 0, line_number = 0, length;
  955.  
  956.   password_file = our_dir;
  957.   strcat (password_file, "WHPASS.TXT");
  958.  
  959.   for (counter = 1; counter <= maxtries; counter = counter + 1) {
  960.                       // Try to open password file
  961.     if (password_file_handle = fopen (password_file, "r")) {
  962.                         // Read next line from file.
  963.       while (fgets (line_from_file, 64, password_file_handle) != -1) {
  964.                         // Check for ^Z termination
  965.         if (line_from_file == "^Z") {
  966.           file_ends_in_control_z = 1;
  967.           break;
  968.         }
  969.         line_number = line_number + 1;
  970.                       // If line is long enough . . .
  971.         if (strlen (line_from_file) >= min_user_name+4) {
  972.                       // Get length of name
  973.           if ( (field_length = strchr (line_from_file, 0, ';')) > 0) {
  974.                       // Get name
  975.             substr (line_from_file, 0, field_length, name_from_file);
  976.                       // If name matches . . . .
  977.             if (strcmpi (name_from_file, current_caller) == 0) {
  978.                       // Get password
  979.               field_start = field_length + 1;
  980.               if ( (field_length = strchr (line_from_file, field_start, ';') - field_start) > 0) {
  981.                 substr (line_from_file, field_start, field_length, password_from_file);
  982.                       // Get working directory
  983.                 field_start = field_start + field_length + 1;
  984.                 if ( (field_length = strchr (line_from_file, field_start, ';') - field_start) >= 0) {
  985.                   substr (line_from_file, field_start, field_length, working_dir);
  986.                       // Get access level
  987.                   field_start = field_start + field_length + 1;
  988.                   substr (line_from_file, field_start, 1, temporary);
  989.                   access_from_file = stoi (temporary);
  990.                       // Set flag that we got an old user
  991.                   found_password = 1;
  992.                   break;
  993.                 }
  994.                 else {
  995.                   password_file_error (line_number, line_from_file, "no third semicolon");
  996.                 }
  997.               }
  998.               else {
  999.                 password_file_error (line_number, line_from_file, "no second semicolon");
  1000.               }
  1001.             }
  1002.           }
  1003.           else {
  1004.             password_file_error (line_number, line_from_file, "no first semicolon");
  1005.           }
  1006.         }
  1007.         else {
  1008.           password_file_error (line_number, line_from_file, "line too short");
  1009.         }
  1010.       }
  1011.       fclose (password_file_handle);
  1012.     }
  1013.     if (found_password) {
  1014.       break;
  1015.     }
  1016.     else {
  1017.       host_send ("^M^JNo user ^"");
  1018.       host_send (current_caller);
  1019.       host_send ("^" on file; re-type name? (y/n): ");
  1020.       host_input_strn (temporary, 1, 1);
  1021.       host_send ("^M^J");
  1022.  
  1023.       if (strcmpi (temporary, "y") != 0) {
  1024.         break;
  1025.       }
  1026.       else {
  1027.         get_user_name ();
  1028.       }
  1029.     }
  1030.   }
  1031.  
  1032.   if (found_password) {
  1033.                       // Password is on file; ask for it
  1034.     host_send ("Password: ");
  1035.     for (counter = 1; counter <= maxtries; counter = counter + 1) {
  1036.       host_input_strn (typed_password, 16, 0);
  1037.                       // If a match
  1038.       if (strcmpi (typed_password, password_from_file) == 0) {
  1039.         host_send ("^M^J");
  1040.           // If the user has a working directory ...
  1041.         if (strcmpi (working_dir, "") != 0) {
  1042.             // Check for a "\" on the end and add it if necessary
  1043.           length = strlen (working_dir);
  1044.           substr (working_dir, length - 1, 1, last_char);
  1045.           if (strcmpi (last_char, "\") != 0) {
  1046.             strcat (working_dir, "\");
  1047.           }
  1048.             // Establish download & upload directories
  1049.           strupper (working_dir);
  1050.           if (check_directory (working_dir)) {
  1051.             _down_dir = working_dir;
  1052.             _up_dir = working_dir;
  1053.             user_has_own_dir = 1;
  1054.           }
  1055.           else {
  1056.             prints ("Using defaults");
  1057.             ustamp (working_dir, 1, 0);
  1058.             ustamp (" does not exist, using default", 0, 1);
  1059.           }
  1060.         }
  1061.           // Return the user's access level
  1062.         return (access_from_file);
  1063.       }
  1064.       if (counter < maxtries) {
  1065.         host_send ("^M^JDoes not match password on file!  Please try again: ");
  1066.       }
  1067.       else {
  1068.         host_send ("^M^JMaximum number of tries exceeded!^M^J");
  1069.       }
  1070.     }
  1071.   }
  1072.                       // Password is not on file
  1073.   else if (!closed_sys) {
  1074.                       // Offer chance to register
  1075.     host_send ("No user  ^"");
  1076.     host_send (current_caller);
  1077.     host_send ("^"  found in user file.^M^JDo you want to register? (Y/N): ");
  1078.     host_input_strn (temporary, 1, 1);
  1079.     host_send ("^M^J");
  1080.                       // If user doesn't want to register
  1081.     if (not ((temporary == "Y") || (temporary == "y"))) {
  1082.       return (0);
  1083.     }
  1084.                       // If user wants to register
  1085.     host_send ("Pick a password (16 characters maximum): ");
  1086.     host_input_strn (password_from_file, 16, 0);
  1087.                       // Make sure password is right
  1088.     host_send ("^M^JRe-enter your password to verify: ");
  1089.     for (counter = 1; counter <= maxtries; counter = counter + 1) {
  1090.       host_input_strn (typed_password, 16, 0);
  1091.                       // If all is ok
  1092.       if (strcmpi (typed_password, password_from_file) == 0) {
  1093.                       // Build new line for password file
  1094.         line_from_file = current_caller;
  1095.         strcat (line_from_file, ";");
  1096.         strcat (line_from_file, password_from_file);
  1097.         strcat (line_from_file, ";;1 **NEW USER** ");
  1098.         date (curtime(), temporary);
  1099.         strcat (line_from_file, temporary);
  1100.                       // Open password file for appending
  1101. //        password_file_handle = fopen (password_file, "a+");
  1102.         password_file_handle = fopen (password_file, "a");
  1103.         if (file_ends_in_control_z) {
  1104.           fseek (password_file_handle, -1, 2);
  1105.         }
  1106.                       // Now we can write the line
  1107.         fwrite (line_from_file, strlen (line_from_file), password_file_handle);
  1108.         fwrite ("^M^J", 2, password_file_handle);
  1109.         fclose (password_file_handle);
  1110.         host_send ("^M^J");
  1111.                       // Return access level
  1112.         return (1);
  1113.       }
  1114.       if (counter < maxtries){
  1115.         host_send ("^M^JDoes not match!  Please try again: ");
  1116.       }
  1117.       else {
  1118.         host_send ("^M^JMaximum number of tries exceeded!^M^J");
  1119.       }
  1120.     }
  1121.   }
  1122.   return (0);
  1123. }
  1124.  
  1125. //////////////////////////////////////////////////////////////////////////////
  1126. // A routine to print an error message to the local screen when something
  1127. //    is wrong with the password file
  1128.  
  1129. password_file_error (int line_number, str line, str error_specifier) {
  1130.  
  1131.   str line_number_string[4];
  1132.  
  1133.   itos (line_number, line_number_string);
  1134.  
  1135.   prints ("");
  1136.   printsc ("Bad line ");
  1137.   printsc (line_number_string);
  1138.   prints (" in password file:");
  1139.   printsc ("   ^"");
  1140.   printsc (line);
  1141.   prints ("^"");
  1142.   prints (error_specifier);
  1143.  
  1144.   return (1);
  1145. }
  1146.  
  1147. //////////////////////////////////////////////////////////////////////////////
  1148. // returns TRUE if passed filespec is just a filename. Also handles the
  1149. // forward slash as a path separator.
  1150.  
  1151. just_filename(str filespec) {
  1152.  
  1153.   int slash, space;
  1154.  
  1155.   if (strpos(filespec, ":", 0) != -1)
  1156.     return 0;
  1157.   if (strpos(filespec, "\", 0) != -1)
  1158.     return 0;
  1159.   if ((slash = strpos(filespec, "/")) == -1)
  1160.     return 1;
  1161.  
  1162.   space = strpos(filespec, " ");
  1163.   if (space == -1)
  1164.     return 0;
  1165.   if (space < slash)
  1166.     return 1;
  1167.  
  1168.   return 0;
  1169.  
  1170. }
  1171.  
  1172. //////////////////////////////////////////////////////////////////////////////
  1173.  
  1174. host_show_directory (str dir_spec) {
  1175.   str file_name[13], f_name_ext[12], f_size_str[20], f_date_str[20],
  1176.       f_time_str[20], buffer[80], path[67], full_name[80],
  1177.       temp[26], hours_str[2], minutes_str[2], seconds_str[2];
  1178.  
  1179.   int file_exists, fsize, ftime, lines, dot_pos, bps, seconds,
  1180.       minutes, hours;
  1181.  
  1182.   bps = get_baud (1);
  1183.  
  1184.   fnstrip (dir_spec, 12, path);
  1185.  
  1186.   file_exists = FileFind (dir_spec, 0, file_name);
  1187.  
  1188.   if (!file_exists) {
  1189.     host_send ("^M^JNo matching file found.^M^J");
  1190.   }
  1191.   else {
  1192.     lines = 2;
  1193. //  host_send ("        Name          Size      Date     Time      ESTIMATED Zmodem^M^J");
  1194. //  host_send ("                                                   transfer time^M^J");
  1195.     host_send ("        Name          Size      Date     Time^M^J");
  1196.   }
  1197.  
  1198.   while (file_exists) {
  1199.  
  1200.     // Get the file size, as a string, with commas where appropriate
  1201.     fsize = FileSize ("");
  1202.     ItoS (fsize, temp);
  1203.     insert_commas (temp, f_size_str);
  1204.  
  1205.     // Get the file date and time as a string
  1206.     ftime = FileTime ("");
  1207.     Date (ftime, f_date_str);
  1208.     Time (ftime, f_time_str);
  1209.  
  1210.     // Estimate how long it'll take to transfer the file with Zmodem
  1211.     seconds = (fsize*10)/bps;
  1212.     // Guess at about 95% efficiency
  1213.     seconds = seconds + seconds/20;
  1214.     if (seconds == 0) {
  1215.       seconds = 1;
  1216.     }
  1217.     minutes = seconds/60;
  1218.     seconds = seconds - minutes*60;
  1219.     hours = minutes/60;
  1220.     minutes = minutes - hours*60;
  1221.  
  1222.     // Convert the transfer time to a string
  1223.     if (seconds < 10) {
  1224.       ItoS (seconds, temp);
  1225.       seconds_str = "0";
  1226.       strcat (seconds_str, temp);
  1227.     }
  1228.     else {
  1229.       ItoS (seconds, seconds_str);
  1230.     }
  1231.     if (minutes < 10) {
  1232.       ItoS (minutes, temp);
  1233.       minutes_str = "0";
  1234.       strcat (minutes_str, temp);
  1235.     }
  1236.     else {
  1237.       ItoS (minutes, minutes_str);
  1238.     }
  1239.     ItoS (hours, hours_str);
  1240.  
  1241.     // Stuff the buffer with just enough spaces so the periods in the
  1242.     //  file names line up
  1243.     dot_pos = strpos (file_name, ".", 0);
  1244.     if (dot_pos > 0) {
  1245.       substr ("        ", 0, 8 - dot_pos, buffer);
  1246.     }
  1247.     else {
  1248.       substr ("        ", 0, 8 - strlen (file_name), buffer);
  1249.     }
  1250.  
  1251.     // Put the file name into the buffer
  1252.     strcat (buffer, file_name);
  1253.  
  1254.     // Append just enough spaces to the buffer to make the right sides of
  1255.     //  the file sizes line up
  1256.     substr ("              ", 0, 26 - strlen (buffer) - strlen (f_size_str), temp);
  1257.     strcat (buffer, temp);
  1258.  
  1259.     // Put the file size into the buffer
  1260.     strcat (buffer, f_size_str);
  1261.  
  1262.     // Put the file date and time into the buffer
  1263.     strcat (buffer, "  ");
  1264.     strcat (buffer, f_date_str);
  1265.     strcat (buffer, " ");
  1266.     strcat (buffer, f_time_str);
  1267.  
  1268.     // Put the transfer time into the buffer
  1269. //  if (hours < 10) {
  1270. //    strcat (buffer, "   ");
  1271. //  }
  1272. //  else {
  1273. //    strcat (buffer, "  ");
  1274. //  }
  1275. //  strcat (buffer, hours_str);
  1276. //  strcat (buffer, ":");
  1277. //  strcat (buffer, minutes_str);
  1278. //  strcat (buffer, ":");
  1279. //  strcat (buffer, seconds_str);
  1280.  
  1281.     // See if we've filled a screen yet ...
  1282.     if (lines > 23) {
  1283.       host_send ("[More]");
  1284.       host_input (1);
  1285.       lines = 0;
  1286.     }
  1287.     else {
  1288.       lines = lines + 1;
  1289.     }
  1290.  
  1291.     // Send the line
  1292.     host_send (buffer);
  1293.     host_send ("^M^J");
  1294.  
  1295.     file_exists = FileFind ("", 0, file_name);
  1296.   }
  1297.  
  1298. }
  1299.  
  1300. //////////////////////////////////////////////////////////////////////////////
  1301.  
  1302. // Insert commas into a string representation of an integer, up to
  1303. //  999,999,999,999 (the largest SALT integer is 2,147,483,647)
  1304.  
  1305. insert_commas (str input, str output) {
  1306.  
  1307.   str tmp1[15], tmp2[15];
  1308.   int len, delta;
  1309.  
  1310.   output = input;
  1311.  
  1312.   for (delta = 3; delta <= 11; delta = delta + 4) {
  1313.     if ((len = strlen (output)) > delta) {
  1314.       substr (output, 0, len - delta, tmp1);
  1315.       substr (output, len - delta, 15, tmp2);
  1316.       output = tmp1;
  1317.       strcat (output, ",");
  1318.       strcat (output, tmp2);
  1319.     }
  1320.     else {
  1321.       break;
  1322.     }
  1323.   }
  1324. }
  1325.  
  1326. //////////////////////////////////////////////////////////////////////////////
  1327.  
  1328. send_goodbye () {
  1329.   str s[80];
  1330.  
  1331.   if (type_file("GOODBYE.MSG") == -1) {
  1332.     s = our_dir;
  1333.     strcat (s, "GOODBYE.MSG");
  1334.     if (type_file (s) == -1) {
  1335.       host_send ("^M^JGoodbye^M^J");
  1336.     }
  1337.   }
  1338.   delay_scr(20);
  1339. }
  1340.  
  1341. //////////////////////////////////////////////////////////////////////////////
  1342.  
  1343. get_user_name () {
  1344.  
  1345.   str temporary[1];
  1346.  
  1347.   while (1) {
  1348.     host_send("Please enter your full name: ");
  1349.     host_input_strn(current_caller, 30, 1);
  1350.     host_send("^M^J");
  1351.  
  1352.     if (finished_caller)
  1353.       return;
  1354.  
  1355.     if (strlen(current_caller) >= min_user_name) {
  1356.       host_send ("^"");
  1357.       host_send (current_caller);
  1358.       host_send ("^", correct? (y/n): ");
  1359.       host_input_strn (temporary, 1, 1);
  1360.       host_send ("^M^J");
  1361.  
  1362.       if (strcmpi (temporary, "y") == 0)
  1363.         break;
  1364.     }
  1365.     else
  1366.       host_send ("Name too short!^M^J");
  1367.   }
  1368. }
  1369.